// Copyright 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "cc/tiles/picture_layer_tiling_set.h"

#include <map>
#include <vector>

#include "base/memory/ptr_util.h"
#include "cc/resources/resource_provider.h"
#include "cc/test/fake_output_surface.h"
#include "cc/test/fake_output_surface_client.h"
#include "cc/test/fake_picture_layer_tiling_client.h"
#include "cc/test/fake_raster_source.h"
#include "cc/test/fake_resource_provider.h"
#include "cc/test/test_shared_bitmap_manager.h"
#include "cc/trees/layer_tree_settings.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/geometry/size_conversions.h"

namespace cc {
namespace {

    class TestablePictureLayerTilingSet : public PictureLayerTilingSet {
    public:
        TestablePictureLayerTilingSet(
            WhichTree tree,
            PictureLayerTilingClient* client,
            int tiling_interest_area_padding,
            float skewport_target_time_in_seconds,
            int skewport_extrapolation_limit_in_screen_pixels,
            float max_preraster_distance)
            : PictureLayerTilingSet(tree,
                client,
                tiling_interest_area_padding,
                skewport_target_time_in_seconds,
                skewport_extrapolation_limit_in_screen_pixels,
                max_preraster_distance)
        {
        }

        using PictureLayerTilingSet::ComputeSkewport;
        using PictureLayerTilingSet::ComputeSoonBorderRect;
        using PictureLayerTilingSet::TilingsNeedUpdate;
    };

    std::unique_ptr<TestablePictureLayerTilingSet> CreateTilingSetWithSettings(
        PictureLayerTilingClient* client,
        const LayerTreeSettings& settings)
    {
        return base::MakeUnique<TestablePictureLayerTilingSet>(
            ACTIVE_TREE, client, settings.tiling_interest_area_padding,
            settings.skewport_target_time_in_seconds,
            settings.skewport_extrapolation_limit_in_screen_pixels,
            settings.max_preraster_distance_in_screen_pixels);
    }

    std::unique_ptr<TestablePictureLayerTilingSet> CreateTilingSet(
        PictureLayerTilingClient* client)
    {
        return CreateTilingSetWithSettings(client, LayerTreeSettings());
    }

    TEST(PictureLayerTilingSetTest, NoResources)
    {
        FakePictureLayerTilingClient client;
        gfx::Size layer_bounds(1000, 800);
        std::unique_ptr<TestablePictureLayerTilingSet> set = CreateTilingSet(&client);
        client.SetTileSize(gfx::Size(256, 256));

        scoped_refptr<FakeRasterSource> raster_source = FakeRasterSource::CreateEmpty(layer_bounds);

        set->AddTiling(1.0, raster_source);
        set->AddTiling(1.5, raster_source);
        set->AddTiling(2.0, raster_source);

        float contents_scale = 2.0;
        gfx::Size content_bounds(
            gfx::ScaleToCeiledSize(layer_bounds, contents_scale));
        gfx::Rect content_rect(content_bounds);

        Region remaining(content_rect);
        PictureLayerTilingSet::CoverageIterator iter(set.get(), contents_scale,
            content_rect, contents_scale);
        for (; iter; ++iter) {
            gfx::Rect geometry_rect = iter.geometry_rect();
            EXPECT_TRUE(content_rect.Contains(geometry_rect));
            ASSERT_TRUE(remaining.Contains(geometry_rect));
            remaining.Subtract(geometry_rect);

            // No tiles have resources, so no iter represents a real tile.
            EXPECT_FALSE(*iter);
        }
        EXPECT_TRUE(remaining.IsEmpty());
    }

    TEST(PictureLayerTilingSetTest, TilingRange)
    {
        FakePictureLayerTilingClient client;
        gfx::Size layer_bounds(10, 10);
        PictureLayerTilingSet::TilingRange higher_than_high_res_range(0, 0);
        PictureLayerTilingSet::TilingRange high_res_range(0, 0);
        PictureLayerTilingSet::TilingRange between_high_and_low_res_range(0, 0);
        PictureLayerTilingSet::TilingRange low_res_range(0, 0);
        PictureLayerTilingSet::TilingRange lower_than_low_res_range(0, 0);
        PictureLayerTiling* high_res_tiling;
        PictureLayerTiling* low_res_tiling;

        scoped_refptr<FakeRasterSource> raster_source = FakeRasterSource::CreateFilled(layer_bounds);

        std::unique_ptr<TestablePictureLayerTilingSet> set = CreateTilingSet(&client);
        set->AddTiling(2.0, raster_source);
        high_res_tiling = set->AddTiling(1.0, raster_source);
        high_res_tiling->set_resolution(HIGH_RESOLUTION);
        set->AddTiling(0.5, raster_source);
        low_res_tiling = set->AddTiling(0.25, raster_source);
        low_res_tiling->set_resolution(LOW_RESOLUTION);
        set->AddTiling(0.125, raster_source);

        higher_than_high_res_range = set->GetTilingRange(PictureLayerTilingSet::HIGHER_THAN_HIGH_RES);
        EXPECT_EQ(0u, higher_than_high_res_range.start);
        EXPECT_EQ(1u, higher_than_high_res_range.end);

        high_res_range = set->GetTilingRange(PictureLayerTilingSet::HIGH_RES);
        EXPECT_EQ(1u, high_res_range.start);
        EXPECT_EQ(2u, high_res_range.end);

        between_high_and_low_res_range = set->GetTilingRange(PictureLayerTilingSet::BETWEEN_HIGH_AND_LOW_RES);
        EXPECT_EQ(2u, between_high_and_low_res_range.start);
        EXPECT_EQ(3u, between_high_and_low_res_range.end);

        low_res_range = set->GetTilingRange(PictureLayerTilingSet::LOW_RES);
        EXPECT_EQ(3u, low_res_range.start);
        EXPECT_EQ(4u, low_res_range.end);

        lower_than_low_res_range = set->GetTilingRange(PictureLayerTilingSet::LOWER_THAN_LOW_RES);
        EXPECT_EQ(4u, lower_than_low_res_range.start);
        EXPECT_EQ(5u, lower_than_low_res_range.end);

        std::unique_ptr<TestablePictureLayerTilingSet> set_without_low_res = CreateTilingSet(&client);
        set_without_low_res->AddTiling(2.0, raster_source);
        high_res_tiling = set_without_low_res->AddTiling(1.0, raster_source);
        high_res_tiling->set_resolution(HIGH_RESOLUTION);
        set_without_low_res->AddTiling(0.5, raster_source);
        set_without_low_res->AddTiling(0.25, raster_source);

        higher_than_high_res_range = set_without_low_res->GetTilingRange(
            PictureLayerTilingSet::HIGHER_THAN_HIGH_RES);
        EXPECT_EQ(0u, higher_than_high_res_range.start);
        EXPECT_EQ(1u, higher_than_high_res_range.end);

        high_res_range = set_without_low_res->GetTilingRange(PictureLayerTilingSet::HIGH_RES);
        EXPECT_EQ(1u, high_res_range.start);
        EXPECT_EQ(2u, high_res_range.end);

        between_high_and_low_res_range = set_without_low_res->GetTilingRange(
            PictureLayerTilingSet::BETWEEN_HIGH_AND_LOW_RES);
        EXPECT_EQ(2u, between_high_and_low_res_range.start);
        EXPECT_EQ(4u, between_high_and_low_res_range.end);

        low_res_range = set_without_low_res->GetTilingRange(PictureLayerTilingSet::LOW_RES);
        EXPECT_EQ(0u, low_res_range.end - low_res_range.start);

        lower_than_low_res_range = set_without_low_res->GetTilingRange(
            PictureLayerTilingSet::LOWER_THAN_LOW_RES);
        EXPECT_EQ(0u, lower_than_low_res_range.end - lower_than_low_res_range.start);

        std::unique_ptr<TestablePictureLayerTilingSet>
            set_with_only_high_and_low_res = CreateTilingSet(&client);
        high_res_tiling = set_with_only_high_and_low_res->AddTiling(1.0, raster_source);
        high_res_tiling->set_resolution(HIGH_RESOLUTION);
        low_res_tiling = set_with_only_high_and_low_res->AddTiling(0.5, raster_source);
        low_res_tiling->set_resolution(LOW_RESOLUTION);

        higher_than_high_res_range = set_with_only_high_and_low_res->GetTilingRange(
            PictureLayerTilingSet::HIGHER_THAN_HIGH_RES);
        EXPECT_EQ(0u,
            higher_than_high_res_range.end - higher_than_high_res_range.start);

        high_res_range = set_with_only_high_and_low_res->GetTilingRange(
            PictureLayerTilingSet::HIGH_RES);
        EXPECT_EQ(0u, high_res_range.start);
        EXPECT_EQ(1u, high_res_range.end);

        between_high_and_low_res_range = set_with_only_high_and_low_res->GetTilingRange(
            PictureLayerTilingSet::BETWEEN_HIGH_AND_LOW_RES);
        EXPECT_EQ(0u, between_high_and_low_res_range.end - between_high_and_low_res_range.start);

        low_res_range = set_with_only_high_and_low_res->GetTilingRange(
            PictureLayerTilingSet::LOW_RES);
        EXPECT_EQ(1u, low_res_range.start);
        EXPECT_EQ(2u, low_res_range.end);

        lower_than_low_res_range = set_with_only_high_and_low_res->GetTilingRange(
            PictureLayerTilingSet::LOWER_THAN_LOW_RES);
        EXPECT_EQ(0u, lower_than_low_res_range.end - lower_than_low_res_range.start);

        std::unique_ptr<TestablePictureLayerTilingSet> set_with_only_high_res = CreateTilingSet(&client);
        high_res_tiling = set_with_only_high_res->AddTiling(1.0, raster_source);
        high_res_tiling->set_resolution(HIGH_RESOLUTION);

        higher_than_high_res_range = set_with_only_high_res->GetTilingRange(
            PictureLayerTilingSet::HIGHER_THAN_HIGH_RES);
        EXPECT_EQ(0u,
            higher_than_high_res_range.end - higher_than_high_res_range.start);

        high_res_range = set_with_only_high_res->GetTilingRange(PictureLayerTilingSet::HIGH_RES);
        EXPECT_EQ(0u, high_res_range.start);
        EXPECT_EQ(1u, high_res_range.end);

        between_high_and_low_res_range = set_with_only_high_res->GetTilingRange(
            PictureLayerTilingSet::BETWEEN_HIGH_AND_LOW_RES);
        EXPECT_EQ(0u, between_high_and_low_res_range.end - between_high_and_low_res_range.start);

        low_res_range = set_with_only_high_res->GetTilingRange(PictureLayerTilingSet::LOW_RES);
        EXPECT_EQ(0u, low_res_range.end - low_res_range.start);

        lower_than_low_res_range = set_with_only_high_res->GetTilingRange(
            PictureLayerTilingSet::LOWER_THAN_LOW_RES);
        EXPECT_EQ(0u, lower_than_low_res_range.end - lower_than_low_res_range.start);
    }

    class PictureLayerTilingSetTestWithResources : public testing::Test {
    public:
        void RunTest(int num_tilings,
            float min_scale,
            float scale_increment,
            float ideal_contents_scale,
            float expected_scale)
        {
            scoped_refptr<TestContextProvider> context_provider = TestContextProvider::Create();
            ASSERT_TRUE(context_provider->BindToCurrentThread());
            auto shared_bitmap_manager = base::MakeUnique<TestSharedBitmapManager>();
            std::unique_ptr<ResourceProvider> resource_provider = FakeResourceProvider::Create(context_provider.get(),
                shared_bitmap_manager.get());

            FakePictureLayerTilingClient client(resource_provider.get());
            client.SetTileSize(gfx::Size(256, 256));
            gfx::Size layer_bounds(1000, 800);
            std::unique_ptr<TestablePictureLayerTilingSet> set = CreateTilingSet(&client);
            scoped_refptr<FakeRasterSource> raster_source = FakeRasterSource::CreateFilled(layer_bounds);

            float scale = min_scale;
            for (int i = 0; i < num_tilings; ++i, scale += scale_increment) {
                PictureLayerTiling* tiling = set->AddTiling(scale, raster_source);
                tiling->set_resolution(HIGH_RESOLUTION);
                tiling->CreateAllTilesForTesting();
                std::vector<Tile*> tiles = tiling->AllTilesForTesting();
                client.tile_manager()->InitializeTilesWithResourcesForTesting(tiles);
            }

            float max_contents_scale = scale;
            gfx::Size content_bounds(
                gfx::ScaleToCeiledSize(layer_bounds, max_contents_scale));
            gfx::Rect content_rect(content_bounds);

            Region remaining(content_rect);
            PictureLayerTilingSet::CoverageIterator iter(
                set.get(), max_contents_scale, content_rect, ideal_contents_scale);
            for (; iter; ++iter) {
                gfx::Rect geometry_rect = iter.geometry_rect();
                EXPECT_TRUE(content_rect.Contains(geometry_rect));
                ASSERT_TRUE(remaining.Contains(geometry_rect));
                remaining.Subtract(geometry_rect);

                float scale = iter.CurrentTiling()->contents_scale();
                EXPECT_EQ(expected_scale, scale);

                if (num_tilings)
                    EXPECT_TRUE(*iter);
                else
                    EXPECT_FALSE(*iter);
            }
            EXPECT_TRUE(remaining.IsEmpty());
        }
    };

    TEST_F(PictureLayerTilingSetTestWithResources, NoTilings)
    {
        RunTest(0, 0.f, 0.f, 2.f, 0.f);
    }
    TEST_F(PictureLayerTilingSetTestWithResources, OneTiling_Smaller)
    {
        RunTest(1, 1.f, 0.f, 2.f, 1.f);
    }
    TEST_F(PictureLayerTilingSetTestWithResources, OneTiling_Larger)
    {
        RunTest(1, 3.f, 0.f, 2.f, 3.f);
    }
    TEST_F(PictureLayerTilingSetTestWithResources, TwoTilings_Smaller)
    {
        RunTest(2, 1.f, 1.f, 3.f, 2.f);
    }

    TEST_F(PictureLayerTilingSetTestWithResources, TwoTilings_SmallerEqual)
    {
        RunTest(2, 1.f, 1.f, 2.f, 2.f);
    }

    TEST_F(PictureLayerTilingSetTestWithResources, TwoTilings_LargerEqual)
    {
        RunTest(2, 1.f, 1.f, 1.f, 1.f);
    }

    TEST_F(PictureLayerTilingSetTestWithResources, TwoTilings_Larger)
    {
        RunTest(2, 2.f, 8.f, 1.f, 2.f);
    }

    TEST_F(PictureLayerTilingSetTestWithResources, ManyTilings_Equal)
    {
        RunTest(10, 1.f, 1.f, 5.f, 5.f);
    }

    TEST_F(PictureLayerTilingSetTestWithResources, ManyTilings_NotEqual)
    {
        RunTest(10, 1.f, 1.f, 4.5f, 5.f);
    }

    TEST(PictureLayerTilingSetTest, TileSizeChange)
    {
        FakePictureLayerTilingClient pending_client;
        FakePictureLayerTilingClient active_client;
        std::unique_ptr<PictureLayerTilingSet> pending_set = PictureLayerTilingSet::Create(PENDING_TREE, &pending_client, 1000, 1.f,
            1000, 1000.f);
        std::unique_ptr<PictureLayerTilingSet> active_set = PictureLayerTilingSet::Create(ACTIVE_TREE, &active_client, 1000, 1.f,
            1000, 1000.f);

        gfx::Size layer_bounds(100, 100);
        scoped_refptr<FakeRasterSource> raster_source = FakeRasterSource::CreateFilled(layer_bounds);

        gfx::Size tile_size1(10, 10);
        gfx::Size tile_size2(30, 30);
        gfx::Size tile_size3(20, 20);

        pending_client.SetTileSize(tile_size1);
        pending_set->AddTiling(1.f, raster_source);
        // New tilings get the correct tile size.
        EXPECT_EQ(tile_size1, pending_set->tiling_at(0)->tile_size());

        // Set some expected things for the tiling set to function.
        pending_set->tiling_at(0)->set_resolution(HIGH_RESOLUTION);
        active_client.set_twin_tiling_set(pending_set.get());

        // Set a priority rect so we get tiles.
        pending_set->UpdateTilePriorities(gfx::Rect(layer_bounds), 1.f, 1.0,
            Occlusion(), false);
        EXPECT_EQ(tile_size1, pending_set->tiling_at(0)->tile_size());

        // The tiles should get the correct size.
        std::vector<Tile*> pending_tiles = pending_set->tiling_at(0)->AllTilesForTesting();
        EXPECT_GT(pending_tiles.size(), 0u);
        for (auto* tile : pending_tiles)
            EXPECT_EQ(tile_size1, tile->content_rect().size());

        // Update to a new source frame with a new tile size.
        // Note that setting a new raster source can typically only happen after
        // activation, since we can't set the raster source twice on the pending tree
        // without activating. For test, just remove and add a new tiling instead.
        pending_set->RemoveAllTilings();
        pending_set->AddTiling(1.f, raster_source);
        pending_set->tiling_at(0)->set_resolution(HIGH_RESOLUTION);
        pending_client.SetTileSize(tile_size2);
        pending_set->UpdateTilingsToCurrentRasterSourceForCommit(raster_source.get(),
            Region(), 1.f, 1.f);
        // The tiling should get the correct tile size.
        EXPECT_EQ(tile_size2, pending_set->tiling_at(0)->tile_size());

        // Set a priority rect so we get tiles.
        pending_set->UpdateTilePriorities(gfx::Rect(layer_bounds), 1.f, 2.0,
            Occlusion(), false);
        EXPECT_EQ(tile_size2, pending_set->tiling_at(0)->tile_size());

        // Tiles should have the new correct size.
        pending_tiles = pending_set->tiling_at(0)->AllTilesForTesting();
        EXPECT_GT(pending_tiles.size(), 0u);
        for (auto* tile : pending_tiles)
            EXPECT_EQ(tile_size2, tile->content_rect().size());

        // Clone from the pending to the active tree.
        active_client.SetTileSize(tile_size2);
        active_set->UpdateTilingsToCurrentRasterSourceForActivation(
            raster_source.get(), pending_set.get(), Region(), 1.f, 1.f);
        // The active tiling should get the right tile size.
        EXPECT_EQ(tile_size2, active_set->tiling_at(0)->tile_size());

        // Cloned tiles should have the right size.
        std::vector<Tile*> active_tiles = active_set->tiling_at(0)->AllTilesForTesting();
        EXPECT_GT(active_tiles.size(), 0u);
        for (auto* tile : active_tiles)
            EXPECT_EQ(tile_size2, tile->content_rect().size());

        // A new source frame with a new tile size.
        pending_client.SetTileSize(tile_size3);
        pending_set->UpdateTilingsToCurrentRasterSourceForCommit(raster_source.get(),
            Region(), 1.f, 1.f);
        // The tiling gets the new size correctly.
        EXPECT_EQ(tile_size3, pending_set->tiling_at(0)->tile_size());

        // Set a priority rect so we get tiles.
        pending_set->UpdateTilePriorities(gfx::Rect(layer_bounds), 1.f, 3.0,
            Occlusion(), false);
        EXPECT_EQ(tile_size3, pending_set->tiling_at(0)->tile_size());

        // Tiles are resized for the new size.
        pending_tiles = pending_set->tiling_at(0)->AllTilesForTesting();
        EXPECT_GT(pending_tiles.size(), 0u);
        for (auto* tile : pending_tiles)
            EXPECT_EQ(tile_size3, tile->content_rect().size());

        // Now we activate with a different tile size for the active tiling.
        active_client.SetTileSize(tile_size3);
        active_set->UpdateTilingsToCurrentRasterSourceForActivation(
            raster_source.get(), pending_set.get(), Region(), 1.f, 1.f);
        // The active tiling changes its tile size.
        EXPECT_EQ(tile_size3, active_set->tiling_at(0)->tile_size());

        // And its tiles are resized.
        active_tiles = active_set->tiling_at(0)->AllTilesForTesting();
        EXPECT_GT(active_tiles.size(), 0u);
        for (auto* tile : active_tiles)
            EXPECT_EQ(tile_size3, tile->content_rect().size());
    }

    TEST(PictureLayerTilingSetTest, MaxContentScale)
    {
        FakePictureLayerTilingClient pending_client;
        FakePictureLayerTilingClient active_client;
        std::unique_ptr<PictureLayerTilingSet> pending_set = PictureLayerTilingSet::Create(PENDING_TREE, &pending_client, 1000, 1.f,
            1000, 1000.f);
        std::unique_ptr<PictureLayerTilingSet> active_set = PictureLayerTilingSet::Create(ACTIVE_TREE, &active_client, 1000, 1.f,
            1000, 1000.f);

        gfx::Size layer_bounds(100, 105);
        scoped_refptr<FakeRasterSource> raster_source = FakeRasterSource::CreateEmpty(layer_bounds);

        // Tilings can be added of any scale, the tiling client can controls this.
        pending_set->AddTiling(1.f, raster_source);
        pending_set->AddTiling(2.f, raster_source);
        pending_set->AddTiling(3.f, raster_source);

        // Set some expected things for the tiling set to function.
        pending_set->tiling_at(0)->set_resolution(HIGH_RESOLUTION);
        active_client.set_twin_tiling_set(pending_set.get());

        // Update to a new source frame with a max content scale that is larger than
        // everything.
        float max_content_scale = 3.f;
        pending_set->UpdateTilingsToCurrentRasterSourceForCommit(
            raster_source.get(), Region(), 1.f, max_content_scale);

        // All the tilings are there still.
        EXPECT_EQ(3u, pending_set->num_tilings());

        // Clone from the pending to the active tree with the same max content size.
        active_set->UpdateTilingsToCurrentRasterSourceForActivation(
            raster_source.get(), pending_set.get(), Region(), 1.f, max_content_scale);
        // All the tilings are on the active tree.
        EXPECT_EQ(3u, active_set->num_tilings());

        // Update to a new source frame with a max content scale that will drop one
        // tiling.
        max_content_scale = 2.9f;
        pending_set->UpdateTilingsToCurrentRasterSourceForCommit(
            raster_source.get(), Region(), 1.f, max_content_scale);
        // All the tilings are there still.
        EXPECT_EQ(2u, pending_set->num_tilings());

        pending_set->tiling_at(0)->set_resolution(HIGH_RESOLUTION);

        // Clone from the pending to the active tree with the same max content size.
        active_set->UpdateTilingsToCurrentRasterSourceForActivation(
            raster_source.get(), pending_set.get(), Region(), 1.f, max_content_scale);
        // All the tilings are on the active tree.
        EXPECT_EQ(2u, active_set->num_tilings());
    }

    TEST(PictureLayerTilingSetTest, SkewportLimits)
    {
        FakePictureLayerTilingClient client;

        gfx::Rect viewport(0, 0, 100, 100);
        gfx::Size layer_bounds(200, 200);

        client.SetTileSize(gfx::Size(100, 100));
        LayerTreeSettings settings;
        settings.skewport_extrapolation_limit_in_screen_pixels = 75;
        settings.tiling_interest_area_padding = 1000000;

        scoped_refptr<FakeRasterSource> raster_source = FakeRasterSource::CreateFilled(layer_bounds);
        std::unique_ptr<TestablePictureLayerTilingSet> tiling_set = CreateTilingSetWithSettings(&client, settings);

        EXPECT_FALSE(tiling_set->TilingsNeedUpdate(viewport, 1.0));
        tiling_set->AddTiling(1.f, raster_source);
        EXPECT_TRUE(tiling_set->TilingsNeedUpdate(viewport, 1.0));

        tiling_set->UpdateTilePriorities(viewport, 1.f, 1.0, Occlusion(), true);

        // Move viewport down 50 pixels in 0.5 seconds.
        gfx::Rect down_skewport = tiling_set->ComputeSkewport(gfx::Rect(0, 50, 100, 100), 1.5, 1.f);

        EXPECT_EQ(0, down_skewport.x());
        EXPECT_EQ(50, down_skewport.y());
        EXPECT_EQ(100, down_skewport.width());
        EXPECT_EQ(175, down_skewport.height());
        EXPECT_TRUE(down_skewport.Contains(gfx::Rect(0, 50, 100, 100)));

        // Move viewport down 50 and right 10 pixels.
        gfx::Rect down_right_skewport = tiling_set->ComputeSkewport(gfx::Rect(10, 50, 100, 100), 1.5, 1.f);

        EXPECT_EQ(10, down_right_skewport.x());
        EXPECT_EQ(50, down_right_skewport.y());
        EXPECT_EQ(120, down_right_skewport.width());
        EXPECT_EQ(175, down_right_skewport.height());
        EXPECT_TRUE(down_right_skewport.Contains(gfx::Rect(10, 50, 100, 100)));

        // Move viewport left.
        gfx::Rect left_skewport = tiling_set->ComputeSkewport(gfx::Rect(-50, 0, 100, 100), 1.5, 1.f);

        EXPECT_EQ(-125, left_skewport.x());
        EXPECT_EQ(0, left_skewport.y());
        EXPECT_EQ(175, left_skewport.width());
        EXPECT_EQ(100, left_skewport.height());
        EXPECT_TRUE(left_skewport.Contains(gfx::Rect(-50, 0, 100, 100)));

        // Expand viewport.
        gfx::Rect expand_skewport = tiling_set->ComputeSkewport(gfx::Rect(-50, -50, 200, 200), 1.5, 1.f);

        // x and y moved by -75 (-50 - 75 = -125).
        // right side and bottom side moved by 75 [(350 - 125) - (200 - 50) = 75].
        EXPECT_EQ(-125, expand_skewport.x());
        EXPECT_EQ(-125, expand_skewport.y());
        EXPECT_EQ(350, expand_skewport.width());
        EXPECT_EQ(350, expand_skewport.height());
        EXPECT_TRUE(expand_skewport.Contains(gfx::Rect(-50, -50, 200, 200)));

        // Expand the viewport past the limit in all directions.
        gfx::Rect big_expand_skewport = tiling_set->ComputeSkewport(gfx::Rect(-500, -500, 1500, 1500), 1.5, 1.f);

        EXPECT_EQ(-575, big_expand_skewport.x());
        EXPECT_EQ(-575, big_expand_skewport.y());
        EXPECT_EQ(1650, big_expand_skewport.width());
        EXPECT_EQ(1650, big_expand_skewport.height());
        EXPECT_TRUE(big_expand_skewport.Contains(gfx::Rect(-500, -500, 1500, 1500)));

        // Shrink the skewport in all directions.
        gfx::Rect shrink_viewport = tiling_set->ComputeSkewport(gfx::Rect(0, 0, 100, 100), 1.5, 1.f);
        EXPECT_EQ(0, shrink_viewport.x());
        EXPECT_EQ(0, shrink_viewport.y());
        EXPECT_EQ(100, shrink_viewport.width());
        EXPECT_EQ(100, shrink_viewport.height());

        // Move the skewport really far in one direction.
        gfx::Rect move_skewport_far = tiling_set->ComputeSkewport(gfx::Rect(0, 5000, 100, 100), 1.5, 1.f);
        EXPECT_EQ(0, move_skewport_far.x());
        EXPECT_EQ(5000, move_skewport_far.y());
        EXPECT_EQ(100, move_skewport_far.width());
        EXPECT_EQ(175, move_skewport_far.height());
        EXPECT_TRUE(move_skewport_far.Contains(gfx::Rect(0, 5000, 100, 100)));
    }

    TEST(PictureLayerTilingSetTest, ComputeSkewportExtremeCases)
    {
        FakePictureLayerTilingClient client;

        gfx::Size layer_bounds(200, 200);
        client.SetTileSize(gfx::Size(100, 100));
        LayerTreeSettings settings;
        settings.tiling_interest_area_padding = 1000000000;
        scoped_refptr<FakeRasterSource> raster_source = FakeRasterSource::CreateFilled(layer_bounds);
        std::unique_ptr<TestablePictureLayerTilingSet> tiling_set = CreateTilingSetWithSettings(&client, settings);
        tiling_set->AddTiling(1.f, raster_source);

        gfx::Rect viewport1(-1918, 255860, 4010, 2356);
        gfx::Rect viewport2(-7088, -91738, 14212, 8350);
        gfx::Rect viewport3(-12730024, -158883296, 24607540, 14454512);
        double time = 1.0;
        tiling_set->UpdateTilePriorities(viewport1, 1.f, time, Occlusion(), true);
        time += 0.016;
        EXPECT_TRUE(
            tiling_set->ComputeSkewport(viewport2, time, 1.f).Contains(viewport2));
        tiling_set->UpdateTilePriorities(viewport2, 1.f, time, Occlusion(), true);
        time += 0.016;
        EXPECT_TRUE(
            tiling_set->ComputeSkewport(viewport3, time, 1.f).Contains(viewport3));

        // Use a tiling with a large scale, so the viewport times the scale no longer
        // fits into integers, and the viewport is not anywhere close to the tiling.
        PictureLayerTiling* tiling = tiling_set->AddTiling(1000.f, raster_source);
        EXPECT_TRUE(tiling_set->TilingsNeedUpdate(viewport3, time));
        tiling_set->UpdateTilePriorities(viewport3, 1.f, time, Occlusion(), true);
        EXPECT_TRUE(tiling->GetCurrentVisibleRectForTesting().IsEmpty());
    }

    TEST(PictureLayerTilingSetTest, ComputeSkewport)
    {
        FakePictureLayerTilingClient client;

        gfx::Rect viewport(0, 0, 100, 100);
        gfx::Size layer_bounds(200, 200);

        client.SetTileSize(gfx::Size(100, 100));

        scoped_refptr<FakeRasterSource> raster_source = FakeRasterSource::CreateFilled(layer_bounds);
        std::unique_ptr<TestablePictureLayerTilingSet> tiling_set = CreateTilingSet(&client);
        tiling_set->AddTiling(1.f, raster_source);

        tiling_set->UpdateTilePriorities(viewport, 1.f, 1.0, Occlusion(), true);

        // Move viewport down 50 pixels in 0.5 seconds.
        gfx::Rect down_skewport = tiling_set->ComputeSkewport(gfx::Rect(0, 50, 100, 100), 1.5, 1.f);

        EXPECT_EQ(0, down_skewport.x());
        EXPECT_EQ(50, down_skewport.y());
        EXPECT_EQ(100, down_skewport.width());
        EXPECT_EQ(200, down_skewport.height());

        // Shrink viewport.
        gfx::Rect shrink_skewport = tiling_set->ComputeSkewport(gfx::Rect(25, 25, 50, 50), 1.5, 1.f);

        EXPECT_EQ(25, shrink_skewport.x());
        EXPECT_EQ(25, shrink_skewport.y());
        EXPECT_EQ(50, shrink_skewport.width());
        EXPECT_EQ(50, shrink_skewport.height());

        // Move viewport down 50 and right 10 pixels.
        gfx::Rect down_right_skewport = tiling_set->ComputeSkewport(gfx::Rect(10, 50, 100, 100), 1.5, 1.f);

        EXPECT_EQ(10, down_right_skewport.x());
        EXPECT_EQ(50, down_right_skewport.y());
        EXPECT_EQ(120, down_right_skewport.width());
        EXPECT_EQ(200, down_right_skewport.height());

        // Move viewport left.
        gfx::Rect left_skewport = tiling_set->ComputeSkewport(gfx::Rect(-20, 0, 100, 100), 1.5, 1.f);

        EXPECT_EQ(-60, left_skewport.x());
        EXPECT_EQ(0, left_skewport.y());
        EXPECT_EQ(140, left_skewport.width());
        EXPECT_EQ(100, left_skewport.height());

        // Expand viewport in 0.2 seconds.
        gfx::Rect expanded_skewport = tiling_set->ComputeSkewport(gfx::Rect(-5, -5, 110, 110), 1.2, 1.f);

        EXPECT_EQ(-30, expanded_skewport.x());
        EXPECT_EQ(-30, expanded_skewport.y());
        EXPECT_EQ(160, expanded_skewport.width());
        EXPECT_EQ(160, expanded_skewport.height());
    }

    TEST(PictureLayerTilingSetTest, SkewportThroughUpdateTilePriorities)
    {
        FakePictureLayerTilingClient client;

        gfx::Rect viewport(0, 0, 100, 100);
        gfx::Size layer_bounds(200, 200);

        client.SetTileSize(gfx::Size(100, 100));

        scoped_refptr<FakeRasterSource> raster_source = FakeRasterSource::CreateFilled(layer_bounds);
        std::unique_ptr<TestablePictureLayerTilingSet> tiling_set = CreateTilingSet(&client);
        tiling_set->AddTiling(1.f, raster_source);

        tiling_set->UpdateTilePriorities(viewport, 1.f, 1.0, Occlusion(), true);

        // Move viewport down 50 pixels in 0.5 seconds.
        gfx::Rect viewport_50 = gfx::Rect(0, 50, 100, 100);
        gfx::Rect skewport_50 = tiling_set->ComputeSkewport(viewport_50, 1.5, 1.f);

        EXPECT_EQ(gfx::Rect(0, 50, 100, 200), skewport_50);
        tiling_set->UpdateTilePriorities(viewport_50, 1.f, 1.5, Occlusion(), true);

        gfx::Rect viewport_100 = gfx::Rect(0, 100, 100, 100);
        gfx::Rect skewport_100 = tiling_set->ComputeSkewport(viewport_100, 2.0, 1.f);

        EXPECT_EQ(gfx::Rect(0, 100, 100, 200), skewport_100);
        tiling_set->UpdateTilePriorities(viewport_100, 1.f, 2.0, Occlusion(), true);

        // Advance time, but not the viewport.
        gfx::Rect result = tiling_set->ComputeSkewport(viewport_100, 2.5, 1.f);
        // Since the history did advance, we should still get a skewport but a smaller
        // one.
        EXPECT_EQ(gfx::Rect(0, 100, 100, 150), result);
        tiling_set->UpdateTilePriorities(viewport_100, 1.f, 2.5, Occlusion(), true);

        // Advance time again.
        result = tiling_set->ComputeSkewport(viewport_100, 3.0, 1.f);
        EXPECT_EQ(viewport_100, result);
        tiling_set->UpdateTilePriorities(viewport_100, 1.f, 3.0, Occlusion(), true);

        // Ensure we have a skewport.
        gfx::Rect viewport_150 = gfx::Rect(0, 150, 100, 100);
        gfx::Rect skewport_150 = tiling_set->ComputeSkewport(viewport_150, 3.5, 1.f);
        EXPECT_EQ(gfx::Rect(0, 150, 100, 150), skewport_150);
        tiling_set->UpdateTilePriorities(viewport_150, 1.f, 3.5, Occlusion(), true);

        // Advance the viewport, but not the time.
        gfx::Rect viewport_200 = gfx::Rect(0, 200, 100, 100);
        gfx::Rect skewport_200 = tiling_set->ComputeSkewport(viewport_200, 3.5, 1.f);
        EXPECT_EQ(gfx::Rect(0, 200, 100, 300), skewport_200);

        // Ensure that continued calls with the same value, produce the same skewport.
        tiling_set->UpdateTilePriorities(viewport_150, 1.f, 3.5, Occlusion(), true);
        EXPECT_EQ(gfx::Rect(0, 200, 100, 300), skewport_200);
        tiling_set->UpdateTilePriorities(viewport_150, 1.f, 3.5, Occlusion(), true);
        EXPECT_EQ(gfx::Rect(0, 200, 100, 300), skewport_200);

        tiling_set->UpdateTilePriorities(viewport_200, 1.f, 3.5, Occlusion(), true);

        // This should never happen, but advance the viewport yet again keeping the
        // time the same.
        gfx::Rect viewport_250 = gfx::Rect(0, 250, 100, 100);
        gfx::Rect skewport_250 = tiling_set->ComputeSkewport(viewport_250, 3.5, 1.f);
        EXPECT_EQ(viewport_250, skewport_250);
        tiling_set->UpdateTilePriorities(viewport_250, 1.f, 3.5, Occlusion(), true);
    }

    TEST(PictureLayerTilingTest, ViewportDistanceWithScale)
    {
        FakePictureLayerTilingClient client;

        gfx::Rect viewport(0, 0, 100, 100);
        gfx::Size layer_bounds(1500, 1500);

        client.SetTileSize(gfx::Size(10, 10));
        LayerTreeSettings settings;

        // Tiling at 0.25 scale: this should create 47x47 tiles of size 10x10.
        // The reason is that each tile has a one pixel border, so tile at (1, 2)
        // for instance begins at (8, 16) pixels. So tile at (46, 46) will begin at
        // (368, 368) and extend to the end of 1500 * 0.25 = 375 edge of the
        // tiling.
        scoped_refptr<FakeRasterSource> raster_source = FakeRasterSource::CreateFilled(layer_bounds);
        std::unique_ptr<TestablePictureLayerTilingSet> tiling_set = CreateTilingSet(&client);
        auto* tiling = tiling_set->AddTiling(0.25f, raster_source);
        tiling->set_resolution(HIGH_RESOLUTION);
        gfx::Rect viewport_in_content_space = gfx::ScaleToEnclosedRect(viewport, 0.25f);

        tiling_set->UpdateTilePriorities(viewport, 1.f, 1.0, Occlusion(), true);
        auto prioritized_tiles = tiling->UpdateAndGetAllPrioritizedTilesForTesting();

        // Compute the soon border.
        gfx::Rect soon_border_rect_in_content_space = tiling_set->ComputeSoonBorderRect(viewport, 1.f);
        soon_border_rect_in_content_space = gfx::ScaleToEnclosedRect(soon_border_rect_in_content_space, 0.25f);

        // Sanity checks.
        for (int i = 0; i < 47; ++i) {
            for (int j = 0; j < 47; ++j) {
                EXPECT_TRUE(tiling->TileAt(i, j)) << "i: " << i << " j: " << j;
            }
        }
        for (int i = 0; i < 47; ++i) {
            EXPECT_FALSE(tiling->TileAt(i, 47)) << "i: " << i;
            EXPECT_FALSE(tiling->TileAt(47, i)) << "i: " << i;
        }

        // No movement in the viewport implies that tiles will either be NOW
        // or EVENTUALLY, with the exception of tiles that are between 0 and 312
        // pixels away from the viewport, which will be in the SOON bin.
        bool have_now = false;
        bool have_eventually = false;
        bool have_soon = false;
        for (int i = 0; i < 47; ++i) {
            for (int j = 0; j < 47; ++j) {
                Tile* tile = tiling->TileAt(i, j);
                PrioritizedTile prioritized_tile = prioritized_tiles[tile];
                TilePriority priority = prioritized_tile.priority();

                gfx::Rect tile_rect = tiling->TilingDataForTesting().TileBounds(i, j);
                if (viewport_in_content_space.Intersects(tile_rect)) {
                    EXPECT_EQ(TilePriority::NOW, priority.priority_bin);
                    EXPECT_FLOAT_EQ(0.f, priority.distance_to_visible);
                    have_now = true;
                } else if (soon_border_rect_in_content_space.Intersects(tile_rect)) {
                    EXPECT_EQ(TilePriority::SOON, priority.priority_bin);
                    have_soon = true;
                } else {
                    EXPECT_EQ(TilePriority::EVENTUALLY, priority.priority_bin);
                    EXPECT_GT(priority.distance_to_visible, 0.f);
                    have_eventually = true;
                }
            }
        }

        EXPECT_TRUE(have_now);
        EXPECT_TRUE(have_soon);
        EXPECT_TRUE(have_eventually);

        // Spot check some distances.
        // Tile at 5, 1 should begin at 41x9 in content space (without borders),
        // so the distance to a viewport that ends at 25x25 in content space
        // should be 17 (41 - 25 + 1). In layer space, then that should be
        // 17 / 0.25 = 68 pixels.

        // We can verify that the content rect (with borders) is one pixel off
        // 41,9 8x8 on all sides.
        EXPECT_EQ(tiling->TileAt(5, 1)->content_rect().ToString(), "40,8 10x10");

        TilePriority priority = prioritized_tiles[tiling->TileAt(5, 1)].priority();
        EXPECT_FLOAT_EQ(68.f, priority.distance_to_visible);

        priority = prioritized_tiles[tiling->TileAt(2, 5)].priority();
        EXPECT_FLOAT_EQ(68.f, priority.distance_to_visible);

        priority = prioritized_tiles[tiling->TileAt(3, 4)].priority();
        EXPECT_FLOAT_EQ(40.f, priority.distance_to_visible);

        // Move the viewport down 40 pixels.
        viewport = gfx::Rect(0, 40, 100, 100);
        viewport_in_content_space = gfx::ScaleToEnclosedRect(viewport, 0.25f);
        gfx::Rect skewport_in_content_space = tiling_set->ComputeSkewport(viewport, 2.0, 1.f);
        skewport_in_content_space = gfx::ScaleToEnclosedRect(skewport_in_content_space, 0.25f);

        // Compute the soon border.
        soon_border_rect_in_content_space = tiling_set->ComputeSoonBorderRect(viewport, 1.f);
        soon_border_rect_in_content_space = gfx::ScaleToEnclosedRect(soon_border_rect_in_content_space, 0.25f);

        EXPECT_EQ(0, skewport_in_content_space.x());
        EXPECT_EQ(10, skewport_in_content_space.y());
        EXPECT_EQ(25, skewport_in_content_space.width());
        EXPECT_EQ(35, skewport_in_content_space.height());

        EXPECT_TRUE(tiling_set->TilingsNeedUpdate(viewport, 2.0));
        tiling_set->UpdateTilePriorities(viewport, 1.f, 2.0, Occlusion(), true);
        prioritized_tiles = tiling->UpdateAndGetAllPrioritizedTilesForTesting();

        have_now = false;
        have_eventually = false;
        have_soon = false;

        // Viewport moved, so we expect to find some NOW tiles, some SOON tiles and
        // some EVENTUALLY tiles.
        for (int i = 0; i < 47; ++i) {
            for (int j = 0; j < 47; ++j) {
                Tile* tile = tiling->TileAt(i, j);
                TilePriority priority = prioritized_tiles[tile].priority();

                gfx::Rect tile_rect = tiling->TilingDataForTesting().TileBounds(i, j);
                if (viewport_in_content_space.Intersects(tile_rect)) {
                    EXPECT_EQ(TilePriority::NOW, priority.priority_bin) << "i: " << i
                                                                        << " j: " << j;
                    EXPECT_FLOAT_EQ(0.f, priority.distance_to_visible) << "i: " << i
                                                                       << " j: " << j;
                    have_now = true;
                } else if (skewport_in_content_space.Intersects(tile_rect) || soon_border_rect_in_content_space.Intersects(tile_rect)) {
                    EXPECT_EQ(TilePriority::SOON, priority.priority_bin) << "i: " << i
                                                                         << " j: " << j;
                    EXPECT_GT(priority.distance_to_visible, 0.f) << "i: " << i
                                                                 << " j: " << j;
                    have_soon = true;
                } else {
                    EXPECT_EQ(TilePriority::EVENTUALLY, priority.priority_bin)
                        << "i: " << i << " j: " << j;
                    EXPECT_GT(priority.distance_to_visible, 0.f) << "i: " << i
                                                                 << " j: " << j;
                    have_eventually = true;
                }
            }
        }

        EXPECT_TRUE(have_now);
        EXPECT_TRUE(have_soon);
        EXPECT_TRUE(have_eventually);

        priority = prioritized_tiles[tiling->TileAt(5, 1)].priority();
        EXPECT_FLOAT_EQ(68.f, priority.distance_to_visible);

        priority = prioritized_tiles[tiling->TileAt(2, 5)].priority();
        EXPECT_FLOAT_EQ(28.f, priority.distance_to_visible);

        priority = prioritized_tiles[tiling->TileAt(3, 4)].priority();
        EXPECT_FLOAT_EQ(4.f, priority.distance_to_visible);

        // Change the underlying layer scale.
        tiling_set->UpdateTilePriorities(viewport, 2.0f, 3.0, Occlusion(), true);
        prioritized_tiles = tiling->UpdateAndGetAllPrioritizedTilesForTesting();

        priority = prioritized_tiles[tiling->TileAt(5, 1)].priority();
        EXPECT_FLOAT_EQ(136.f, priority.distance_to_visible);

        priority = prioritized_tiles[tiling->TileAt(2, 5)].priority();
        EXPECT_FLOAT_EQ(56.f, priority.distance_to_visible);

        priority = prioritized_tiles[tiling->TileAt(3, 4)].priority();
        EXPECT_FLOAT_EQ(8.f, priority.distance_to_visible);

        // Test additional scales.
        tiling = tiling_set->AddTiling(0.2f, raster_source);
        tiling->set_resolution(HIGH_RESOLUTION);
        tiling_set->UpdateTilePriorities(viewport, 1.0f, 4.0, Occlusion(), true);
        prioritized_tiles = tiling->UpdateAndGetAllPrioritizedTilesForTesting();

        priority = prioritized_tiles[tiling->TileAt(5, 1)].priority();
        EXPECT_FLOAT_EQ(110.f, priority.distance_to_visible);

        priority = prioritized_tiles[tiling->TileAt(2, 5)].priority();
        EXPECT_FLOAT_EQ(70.f, priority.distance_to_visible);

        priority = prioritized_tiles[tiling->TileAt(3, 4)].priority();
        EXPECT_FLOAT_EQ(60.f, priority.distance_to_visible);

        tiling_set->UpdateTilePriorities(viewport, 0.5f, 5.0, Occlusion(), true);
        prioritized_tiles = tiling->UpdateAndGetAllPrioritizedTilesForTesting();

        priority = prioritized_tiles[tiling->TileAt(5, 1)].priority();
        EXPECT_FLOAT_EQ(55.f, priority.distance_to_visible);

        priority = prioritized_tiles[tiling->TileAt(2, 5)].priority();
        EXPECT_FLOAT_EQ(35.f, priority.distance_to_visible);

        priority = prioritized_tiles[tiling->TileAt(3, 4)].priority();
        EXPECT_FLOAT_EQ(30.f, priority.distance_to_visible);
    }

    TEST(PictureLayerTilingTest, InvalidateAfterComputeTilePriorityRects)
    {
        FakePictureLayerTilingClient pending_client;
        pending_client.SetTileSize(gfx::Size(100, 100));

        scoped_refptr<FakeRasterSource> raster_source = FakeRasterSource::CreateFilled(gfx::Size(100, 100));
        std::unique_ptr<TestablePictureLayerTilingSet> tiling_set = CreateTilingSet(&pending_client);
        auto* pending_tiling = tiling_set->AddTiling(1.f, raster_source);
        pending_tiling->set_resolution(HIGH_RESOLUTION);

        // Ensure that we can compute tile priority rects, invalidate, and compute the
        // rects again. It is important that the second compute tile priority rects
        // return true, indicating that things have changed (since invalidation has
        // changed things). This causes PrepareTiles to be properly scheduled. If the
        // second ComputeTilePriorityRects returns false, then we assume that
        // PrepareTiles isn't needed and we signal that we're ready to draw
        // immediately, which can cause visual glitches.
        //
        // This can happen we if we process an impl frame deadline before processing a
        // commit. That is, when we draw we ComputeTilePriorityRects. If we process
        // the commit afterwards, it would use the same timestamp and sometimes would
        // use the same viewport to compute tile priority rects again.
        double time = 1.;
        gfx::Rect viewport(0, 0, 100, 100);
        EXPECT_TRUE(
            tiling_set->UpdateTilePriorities(viewport, 1.f, time, Occlusion(), true));
        EXPECT_FALSE(
            tiling_set->UpdateTilePriorities(viewport, 1.f, time, Occlusion(), true));

        // This will invalidate tilings.
        tiling_set->UpdateRasterSourceDueToLCDChange(raster_source, Region());

        EXPECT_TRUE(
            tiling_set->UpdateTilePriorities(viewport, 1.f, time, Occlusion(), true));
    }

    TEST(PictureLayerTilingTest, InvalidateAfterUpdateRasterSourceForCommit)
    {
        FakePictureLayerTilingClient pending_client;
        FakePictureLayerTilingClient active_client;
        std::unique_ptr<PictureLayerTilingSet> pending_set = PictureLayerTilingSet::Create(PENDING_TREE, &pending_client, 1000, 1.f,
            1000, 1000.f);
        std::unique_ptr<PictureLayerTilingSet> active_set = PictureLayerTilingSet::Create(ACTIVE_TREE, &active_client, 1000, 1.f,
            1000, 1000.f);

        gfx::Size layer_bounds(100, 100);
        scoped_refptr<FakeRasterSource> raster_source = FakeRasterSource::CreateFilled(layer_bounds);

        auto* pending_tiling = pending_set->AddTiling(1.f, raster_source);
        pending_tiling->set_resolution(HIGH_RESOLUTION);
        active_client.set_twin_tiling_set(pending_set.get());

        double time = 1.;
        gfx::Rect viewport(0, 0, 100, 100);

        // The first commit will update the raster source for pending tilings.
        pending_set->UpdateTilingsToCurrentRasterSourceForCommit(raster_source,
            Region(), 1.f, 1.f);
        // UpdateTilePriorities for pending set gets called during UDP in commit.
        EXPECT_TRUE(pending_set->UpdateTilePriorities(viewport, 1.f, time,
            Occlusion(), true));
        // The active set doesn't have tilings yet.
        EXPECT_FALSE(
            active_set->UpdateTilePriorities(viewport, 1.f, time, Occlusion(), true));

        // On activation tilings are copied from pending set to active set.
        active_set->UpdateTilingsToCurrentRasterSourceForActivation(
            raster_source, pending_set.get(), Region(), 1.f, 1.f);
        // Pending set doesn't have any tilings now.
        EXPECT_FALSE(pending_set->UpdateTilePriorities(viewport, 1.f, time,
            Occlusion(), true));
        // UpdateTilePriorities for active set gets called during UDP in draw.
        EXPECT_TRUE(
            active_set->UpdateTilePriorities(viewport, 1.f, time, Occlusion(), true));

        // Even though frame time and viewport haven't changed since last commit we
        // update tile priorities because of potential invalidations.
        pending_set->UpdateTilingsToCurrentRasterSourceForCommit(raster_source,
            Region(), 1.f, 1.f);
        // UpdateTilePriorities for pending set gets called during UDP in commit.
        EXPECT_TRUE(pending_set->UpdateTilePriorities(viewport, 1.f, time,
            Occlusion(), true));
        // No changes for active set until activation.
        EXPECT_FALSE(
            active_set->UpdateTilePriorities(viewport, 1.f, time, Occlusion(), true));
    }

} // namespace
} // namespace cc
